<template>
  <div class="ad-chart-w">
    <div class="scroll-w">
      <a-scrollbar class="target-wrap-scroll" style="overflow: auto">
        <ul class="flex-c" :style="{ left: left + 'px' }">
          <li class="all-target" v-for="(target, i) in allTargetKeys" :key="i" @click="changeTargetClick(target)">
            <span class="line" :style="{ backgroundColor: advertStore.salesTargetClickKeys.includes(target.key) ? target.color : 'transparent' }"></span>
            <p>
              <span>{{ target.name }}</span>
              <span v-if="target.type == 'price'">({{ currencySymbol[searchParams.currencyCode] }})</span>
              <a-popover v-if="target.tip">
                <template #content>
                  <p style="width: 400px">{{ target.tip }}</p>
                </template>
                <icon-question-circle style="margin-left: 4px" />
              </a-popover>
            </p>
            <p class="value">
              <span class="value-price" v-if="target.type == 'percentage'">{{ formatVal(target, 'value') }}%</span>
              <span class="value-price" v-else>{{ formatVal(target, 'value') }}</span>
            </p>
            <div class="price-item flex-c">
              <span class="label">环比</span>
              <span class="val" v-if="target.type == 'percentage'">{{ formatVal(target, 'monValue') }}%</span>
              <span class="val" v-else>{{ formatVal(target, 'monValue') }}</span>
              <template v-if="Number($extract(targetMap[target.key], 'monComparedValue')) > 0">
                <icon-caret-up style="color: rgb(var(--success-5))" />
                <span class="diff" style="color: rgb(var(--success-5))">{{ Math.abs($extract(targetMap[target.key], 'monComparedValue')) }}%</span>
              </template>
              <template v-else>
                <icon-caret-down style="color: rgb(var(--danger-5))" />
                <span class="diff" style="color: rgb(var(--danger-5))">{{ Math.abs($extract(targetMap[target.key], 'monComparedValue')) }}%</span>
              </template>
            </div>
            <div class="price-item flex-c">
              <span class="label">年同比</span>
              <span class="val" v-if="target.type == 'percentage'">{{ formatVal(target, 'yoyValue') }}%</span>
              <span class="val" v-else>{{ formatVal(target, 'yoyValue') }}</span>
              <template v-if="Number($extract(targetMap[target.key], 'yoyComparedValue')) > 0">
                <icon-caret-up style="color: rgb(var(--success-5))" />
                <span class="diff" style="color: rgb(var(--success-5))">{{ Math.abs($extract(targetMap[target.key], 'yoyComparedValue')) }}%</span>
              </template>
              <template v-else>
                <icon-caret-down style="color: rgb(var(--danger-5))" />
                <span class="diff" style="color: rgb(var(--danger-5))">{{ Math.abs($extract(targetMap[target.key], 'yoyComparedValue')) }}%</span>
              </template>
            </div>
          </li>
        </ul>
      </a-scrollbar>
      <div class="icon-w to-left">
        <icon-left @click="leftSlide" />
      </div>
      <div class="icon-w to-right">
        <icon-right @click="rightSlide" />
      </div>
    </div>

    <a-spin :loading="loading" style="width: 100%; height: 300px">
      <div ref="adChartFef" v-if="advertStore.salesTargetClickKeys && advertStore.salesTargetClickKeys.length" style="height: 300px"></div>
    </a-spin>
  </div>
</template>
<script lang="ts" setup>
  import useEcharts from '@/hooks/useEcharts'
  import { ref, nextTick, onBeforeUnmount } from 'vue'
  import { trendChartsByShop, trendChartsBySku, trendChartsByUser } from '@/api/dataBoard'
  import { dispose } from 'echarts/core'
  import useAdvertStore from '@/store/modules/advert'
  import { currencySymbol } from '@/utils/globalData'
  const props = defineProps({
    searchParams: {
      type: Object,
      default: () => {},
    },
    targetMap: {
      type: Object,
      default: () => {},
    },
    source: {
      type: String,
      default: 'shop',
    },
  })

  const advertStore = useAdvertStore()
  const chartDatas = ref<Array<any>>([])
  const loading = ref(false)
  const timer = ref()
  const left = ref(0)
  const targetList = ref<any>({
    purchasesSale: {
      key: 'purchasesSale',
      name: '销量',
      type: 'num',
      color: '#fac858',
      tip: '1.包含FBA销量、FBM销量和多渠道销量,2.来自payment的order quantity',
    },
    saleAmount: {
      key: 'saleAmount',
      name: '销售额',
      type: 'price',
      color: '#52a1ff',
      tip: '销售额包含pending、unshipped、shipped状态的订单。部分pending状态的订单亚马逊可能没有返回销售额，取在线产品价格预估，可能存在小范围的偏差。',
    },
    returnQuantity: {
      key: 'returnQuantity',
      name: '退货量',
      type: 'num',
      color: '#e751bf',
    },
    refundAmount: {
      key: 'refundAmount',
      name: '退款金额',
      type: 'price',
      color: '#ee6666',
    },
    saleProfit: {
      key: 'saleProfit',
      name: '毛利润',
      type: 'price',
      color: '#5470c6',
      tip: '毛利润=销售额-退货金额-平台佣金-运费-产品成本',
    },
    cost: {
      key: 'cost',
      name: '广告花费',
      type: 'price',
      color: '#91cc75',
    },
    adSaleAmount: {
      key: 'adSaleAmount',
      name: '广告销售额',
      type: 'price',
      color: '#3ba272',
    },
    adPurchasesSale: {
      key: 'adPurchasesSale',
      name: '广告销量',
      type: 'num',
      color: '#fc8452',
    },
    acos: {
      key: 'acos',
      name: 'ACOS',
      type: 'percentage',
      color: '#9a60b4',
      tip: '亚马逊广告投入产出比=广告花费/广告总销售额 * 100%',
    },
    acots: {
      key: 'acots',
      name: 'ACOTS',
      type: 'percentage',
      color: '#9a60b4',
      tip: '广告费与店铺整体销售额的占比计算公式如下:(广告费/整体销售额）x 100%',
    },
    roas: {
      key: 'roas',
      name: 'ROAS',
      type: 'num',
      tip: '广告支出回报=广告销售额/广告花费',
      color: '#ea7ccc',
    },
    asots: {
      key: 'asots',
      name: 'ASOTS',
      type: 'num',
      tip: '广告带来的销售额占总销售额的比例=广告销售额 / 销售额 * 100%',
      color: '#dcff74',
    },
  })
  const apiMap = {
    shop: trendChartsByShop,
    sku: trendChartsBySku,
    user: trendChartsByUser,
  }
  const allTargetKeys = ref<Array<any>>(Object.values(targetList.value))

  // 获取所有指标图表数据
  let dates: Array<any> = []
  let yDataMap = {}

  // 刷新数据
  async function refreshData() {
    await getChartData()
    nextTick(() => {
      initChart()
    })
  }

  // 获取趋势图标数据
  async function getChartData() {
    if (!props.searchParams.startDate) return
    loading.value = true
    const res: any = await apiMap[props.source](props.searchParams)
    loading.value = false
    chartDatas.value = res?.data || []
    dates = chartDatas.value.map((el) => el.date)
    Object.keys(targetList.value).forEach((key) => {
      yDataMap[key] = chartDatas.value.map((el) => Math.abs(el[key]))
    })
  }

  // 滚动指标
  function leftSlide() {
    // 保存滚动盒子左侧已滚动的距离
    let scrollEl = document.querySelector(`.target-wrap-scroll`) as HTMLElement
    let left = scrollEl.scrollLeft
    let num = 0
    clearInterval(timer.value)
    timer.value = null
    timer.value = setInterval(() => {
      //   !left:已经滚动到最左侧
      //   一次性滚动距离（可调节）
      if (!left || num >= 300) {
        // 停止滚动
        clearInterval(timer.value)
        timer.value = null
        return
      }
      // 给滚动盒子元素赋值向左滚动距离
      scrollEl.scrollLeft = left -= 30
      // 保存向左滚动距离（方便判断一次性滚动多少距离）
      num += 30
    }, 20)
  }
  function rightSlide() {
    // 保存滚动盒子左侧已滚动的距离
    let scrollEl = document.querySelector(`.target-wrap-scroll`) as HTMLElement
    let left = scrollEl.scrollLeft
    // 保存元素的整体宽度
    let scrollWidth = scrollEl.scrollWidth
    // 保存元素的可见宽度
    let clientWidth = scrollEl.clientWidth
    let num = 0
    clearInterval(timer.value)
    timer.value = setInterval(() => {
      // 已经滚动距离+可见宽度
      // left+clientWidth>=scrollWidth：滚动到最右侧
      // num>=300一次性滚动距离
      if (left + clientWidth >= scrollWidth || num >= 300) {
        clearInterval(timer.value)
        return
      }
      // 给滚动盒子元素赋值向左滚动距离
      scrollEl.scrollLeft = left += 30
      // 保存向左滚动距离（方便判断一次性滚动多少距离）
      num += 30
    }, 20)
  }
  // 设置需要展示的图表-只展示2个
  function changeTargetClick(item: any) {
    let targetClickKeys = [...advertStore.salesTargetClickKeys]
    let _index = targetClickKeys.indexOf(item.key)
    if (_index > -1) {
      targetClickKeys.splice(_index, 1)
    } else if (targetClickKeys.length == 2) {
      targetClickKeys.splice(0, 1)
      targetClickKeys.push(item.key)
    } else {
      targetClickKeys.push(item.key)
    }
    advertStore.changeSalesTargetClickKey(targetClickKeys)
    nextTick(() => {
      initChart()
    })
  }
  // 数量多以万为单位
  function formatVal(item: any, key: string) {
    let val = Math.abs(props.targetMap[item.key]?.[key] || 0)
    if (val < 100000) {
      return Number(val)
    } else {
      return Number(val / 10000).toFixed(2) + '万'
    }
  }

  const adChartFef = ref<HTMLDivElement | null>(null)
  // 获取series轴信息
  function setSeries() {
    return advertStore.salesTargetClickKeys?.map((key, index) => {
      return {
        name: targetList.value[key]?.name,
        yAxisIndex: index,
        type: key == 'impressions' ? 'bar' : 'line',
        data: yDataMap[key],
        color: targetList.value[key]?.color,
      }
    })
  }
  // 获取Y轴信息
  function setYData() {
    return advertStore.salesTargetClickKeys?.map((key) => {
      let max = Math.max.apply(null, yDataMap[key] || [])
      return {
        type: 'value',
        name: targetList.value[key]?.name,
        min: 0,
        max: setMaxInterval(max).max,
        splitNumber: 5,
        minInterval: 1,
        nameGap: 20,
        interval: setMaxInterval(max).interval,
        axisLine: {
          show: true,
          lineStyle: {
            color: targetList.value[key]?.color,
          },
        },
        axisLabel: {
          formatter(v: any) {
            v = v.toString()
            if (Math.abs(v) >= 100000) {
              return v / 10000 + '万'
            } else {
              return v
            }
          },
        },
      }
    })
  }
  // 为了平均分布Y轴
  function setMaxInterval(max: number) {
    if (max <= 1) {
      return { max: 1, interval: 0.2 }
    }
    if (max <= 5) {
      return { max: 5, interval: 1 }
    }
    if (max <= 10) {
      return { max: 10, interval: 2 }
    }
    if (max <= 50) {
      return { max: 50, interval: 10 }
    }
    if (max <= 100) {
      return { max: 100, interval: 20 }
    }
    if (max <= 500) {
      return { max: 500, interval: 100 }
    }
    if (max <= 1000) {
      return { max: 1000, interval: 200 }
    }
    if (max <= 2000) {
      return { max: 2000, interval: 400 }
    }
    if (max <= 5000) {
      return { max: 5000, interval: 1000 }
    }
    if (max <= 8000) {
      return { max: 8000, interval: 1600 }
    }
    if (max <= 10000) {
      return { max: 10000, interval: 2000 }
    }
    if (max <= 20000) {
      return { max: 20000, interval: 4000 }
    }
    if (max <= 50000) {
      return { max: 50000, interval: 10000 }
    }
    if (max <= 80000) {
      return { max: 80000, interval: 16000 }
    }
    if (max <= 100000) {
      return { max: 100000, interval: 20000 }
    }
    if (max <= 500000) {
      return { max: 500000, interval: 100000 }
    }
    if (max <= 1000000) {
      return { max: 1000000, interval: 200000 }
    }
    if (max <= 2000000) {
      return { max: 2000000, interval: 400000 }
    }
    if (max <= 5000000) {
      return { max: 5000000, interval: 1000000 }
    }
    if (max <= 10000000) {
      return { max: 10000000, interval: 2000000 }
    }
    if (max <= 50000000) {
      return { max: 50000000, interval: 10000000 }
    }
    return {
      max: Math.ceil(max / 5) * 5,
      interval: Math.ceil(max / 5),
    }
  }
  function initChart() {
    // 容易导致重复渲染，先清除
    if (adChartFef.value) {
      dispose(adChartFef.value as HTMLDivElement)
    }
    if (!advertStore.salesTargetClickKeys?.length) return
    const option = {
      grid: {
        left: 50,
        top: 40,
        bottom: 10,
        right: 50,
        containLabel: true,
      },
      tooltip: {
        trigger: 'axis',
        valueFormatter: (v: number) => {
          if (Math.abs(v) >= 100000) {
            return (v / 10000).toFixed(2) + '万'
          } else {
            return v
          }
        },
      },
      xAxis: {
        type: 'category',
        data: dates,
        axisLine: {
          show: true,
          lineStyle: {
            color: '#98A3B2',
            width: 0,
            type: 'solid',
          },
        },
        axisTick: {
          show: false,
        },
      },
      yAxis: setYData(),
      series: setSeries(),
    }
    nextTick(() => useEcharts(adChartFef.value as HTMLDivElement).setOption(option))
  }
  onBeforeUnmount(() => {
    dispose(adChartFef.value as HTMLDivElement)
  })

  defineExpose({ refreshData })
</script>
<style lang="less" scoped>
  .ad-chart-w {
    background-color: #fff;
    overflow: hidden;
    padding: 10px 0;
  }
  .scroll-w {
    padding: 0 10px;
    width: 100%;
    position: relative;
    margin-bottom: 20px;
    .icon-w {
      width: 24px;
      height: 24px;
      background-color: rgba(0, 0, 0, 0.2);
      border-radius: 50%;
      text-align: center;
      line-height: 24px;
      color: #999;
      position: absolute;
      top: 40px;
      cursor: pointer;
      &.to-left {
        left: 10px;
      }
      &.to-right {
        right: 10px;
      }
    }
  }
  :deep(.target-wrap-scroll) {
    border: 1px solid var(--color-border);
  }
  .all-target {
    width: 220px;
    border-right: 1px solid var(--color-border);
    height: 100px;
    padding: 10px 5px 10px 10px;
    position: relative;
    font-size: 12px;
    line-height: 20px;
    flex-shrink: 0;
    &:last-child {
      border-right: 0;
    }
    .value-price {
      font-size: 16px;
      font-weight: bold;
      margin-right: 8px;
    }
    .line {
      position: absolute;
      width: 100%;
      left: 0;
      top: 0;
      height: 2px;
    }
    .price-item {
      .label {
        width: 42px;
      }
      .val {
        margin-right: 5px;
      }
      .arco-icon {
        font-size: 18px;
      }
    }
    .diff {
      margin-left: 5px;
    }
    .delete-icon {
      position: absolute;
      top: 2px;
      cursor: pointer;
      right: 5px;
    }
    &.active {
      border-color: rgba(var(--primary-6), 0.4);
      color: rgba(var(--primary-6), 0.8);
      .arco-icon {
        color: rgba(var(--primary-6), 0.8);
      }
    }
    .arco-icon {
      font-size: 14px;
      color: #666;
      margin-left: 2px;
    }
  }

  :deep(.arco-radio-group-button) {
    padding: 0;
    .arco-radio-button {
      margin: 0;
      background-color: #fff;
      line-height: 26px;
      border: 1px solid var(--color-border);
      &:first-child {
        border-radius: 4px 0 0 4px;
      }
      &:last-child {
        border-radius: 0 4px 4px 0;
      }
    }
    .arco-radio-checked {
      border-color: rgb(var(--primary-6));
    }
  }
</style>
